package org.shangrila.comm.security;

/*
 * by Shangrila 2014-6-18
 * 本类解决登录页面的图片验证问题。
 */

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

public class ValidImageCreater implements Serializable{

	private static final long serialVersionUID = 4L;
	//private final String IMAGE_VALID_MODE="FILE";  //验证模式：FILE生成文件，WEB写入response
	private static final String CODE_LIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz1234567890";
	private HttpServletResponse response = null;
	private static final int HEIGHT = 20;
	private static final int FONT_NUM = 4;
	private int width = 0;
	private int iNum = 0;
	private String codeList = "";
	private boolean drawBgFlag = true;
	private int iRandomLine = 0;  //随机产生155条干扰线
	
	//天蓝灰202,235,216 金黄255,215,0 杏仁灰255,235,205 黑色0,0,0 白色255,255,255
	private int rBg = 202;
	private int gBg = 235;
	private int bBg = 216;
	private StreamedContent pfimage;
	
	//定义三个构造函数
	public ValidImageCreater() {
		this.width = 13 * FONT_NUM + 12;
		this.iNum = FONT_NUM;
		this.codeList = CODE_LIST;
	}
	
	public ValidImageCreater(HttpServletResponse response) {
		this.response = response;
		this.width = 13 * FONT_NUM + 12;
		this.iNum = FONT_NUM;
		this.codeList = CODE_LIST;
	}

	public ValidImageCreater(HttpServletResponse response, int iNum,
			String codeList) {
		this.response = response;
		this.width = 13 * iNum + 12;
		this.iNum = iNum;
		this.codeList = codeList;
	}

	/*
	 * 创建验证图片文件，返回图片上显示的字符
	 */
	public String createRandImage(String mode) {
		return createRandImage();
	}

	/*
	 * 创建验证图片文件，返回图片上显示的字符
	 */
	public String createRandImage() {
		// 在内存中创建图象
		BufferedImage image = new BufferedImage(width, HEIGHT,BufferedImage.TYPE_INT_RGB);
		// 获取图形上下文
		Graphics g = image.getGraphics();
		//生成随机类
		Random random = new Random();
			
		if (drawBgFlag) {
			// 设定背景色
			g.setColor(new Color(rBg, gBg, bBg));
			//画边框
			g.fillRect(0, 0, width, HEIGHT);
		} else {
			// 设定背景色
			g.setColor(getRandColor(200, 250));
			//画边框
			g.fillRect(0, 0, width, HEIGHT);

		}
		
		// 随机产生155条干扰线，使图象中的认证码不易被其它程序探测到
		for (int i = 0; i < iRandomLine; i++) {
			g.setColor(getRandColor(140, 200));
			int x = random.nextInt(width);
			int y = random.nextInt(HEIGHT);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		
		//设定字体
		g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
		String sRand = "";
		// 取随机产生的认证码
		for (int i = 0; i < iNum; i++) {
			int rand = random.nextInt(codeList.length());
			String strRand = codeList.substring(rand, rand + 1);
			sRand += strRand;
			// 将认证码显示到图象中
			g.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));
			//调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
			g.drawString(strRand, 13 * i + 6, 16);
		}

		// 图象生效 同时释放Graphics对象所占用的资源。
		g.dispose();
		try {
			ImageIO.write(image, "JPG", response.getOutputStream());// 输出图象到页面			
		} catch (IOException e) {
			e.printStackTrace();
		}

		return sRand;//将认证码存入
		
	}
	
	public String createValidImage(String filepath) {
		BufferedImage image = new BufferedImage(width, HEIGHT,BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		Random random = new Random();
		if (drawBgFlag) {
			g.setColor(new Color(rBg, gBg, bBg));
			g.fillRect(0, 0, width, HEIGHT);
		} else {
			g.setColor(getRandColor(200, 250));
			g.fillRect(0, 0, width, HEIGHT);
		}

		for (int i = 0; i < iRandomLine; i++) {
			g.setColor(getRandColor(160, 200));
			int x = random.nextInt(width);
			int y = random.nextInt(HEIGHT);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		
		g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
		String sRand = "";
		for (int i = 0; i < iNum; i++) {
			int rand = random.nextInt(codeList.length());
			String strRand = codeList.substring(rand, rand + 1);
			sRand += strRand;
			g.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));
			g.drawString(strRand, 13 * i + 6, 16);
		}

		g.dispose();
		try {
			ImageIO.write(image, "jpg", new File(filepath));// 通过ImageIO对象的write静态方法将图片输出。			
			ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(image, "png", os);
            pfimage = new DefaultStreamedContent(new ByteArrayInputStream(os.toByteArray()), "image/png"); 

		} catch (IOException e) {
			e.printStackTrace();
		}catch (Exception ex){
			ex.printStackTrace();
		}

		return sRand;
	}
	
	//设置背景颜色
	public void setBgColor(int r, int g, int b) {
		drawBgFlag = true;
		this.rBg = r;
		this.gBg = g;
		this.bBg = b;
	}

	//给定范围获得随机颜色
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);

		return new Color(r, g, b);
	}

	public static void Test1() {

		BufferedImage image = new BufferedImage(80, 50,
		BufferedImage.TYPE_INT_RGB);// 建立BufferedImage对象。指定图片的长度宽度和色彩。
		Graphics g = image.getGraphics();// 取得Graphics对象，用来绘制图片。
		g.setColor(new Color(255, 255, 255));// 绘制图片背景和文字。
		g.fillRect(0, 0, 80, 25);
		g.setColor(new Color(0, 0, 0));
		g.drawString("HelloImage", 6, 16);
		g.dispose();// 释放Graphics对象所占用的资源。

		try {
			ImageIO.write(image, "jpeg", new File("d:\\validImage.jpg"));// 通过ImageIO对象的write静态方法将图片输出。
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	
	public static void main(String[] args) {
		//Test1();
		ValidImageCreater rc = new ValidImageCreater();
		System.out.println(rc.createRandImage());
	}

	public StreamedContent getPfimage() {
		return pfimage;
	}

	public void setPfimage(StreamedContent pfimage) {
		this.pfimage = pfimage;
	}

}
